#!/opt/php/bin/php -d open_basedir=
<?php
require_once 'TVB/Message/BaseConsumer.php';
require_once 'TVB/SSH/SSHAgent.php';

require_once 'TVB/ImageInfrastructure/Server/requires.php';

// one consumer per destination
class DistributeTvbImgFarmImageConsumer extends BaseConsumer {
	const IMG_FARM_CONFIG = '/data/image_infrastructure/config/distribute_tvb_img_farm_image/img_farm.xml';
	const ACL_PREFIX='/data/image_infrastructure/acl';

	private $destinations;
	private $port;
	private $user;
	private $passpharse;
	private $public_key_file;
	private $private_key_file;
	private $destination_id;

	public function init($destination_id) {
		$config = ConfigReaderFactory::getInstance()->getConfigReader(self::IMG_FARM_CONFIG)->getConfig();
		$this->destinations = $config->servers->server;
		$this->port = intval($config->port);
		$this->user = $config->user;
		$this->passpharse = $config->passpharse;
		$this->public_key_file = $config->public_key_file;
		$this->private_key_file = $config->private_key_file;
		$this->destination_id = $destination_id;
	}
	
	protected function generateAclFile($export_id) {
		$destination_id = $this->destination_id;
		$rf = ImageInfrastructure::getReadableRecordFactory();
		$export_entry = $rf->findInstance('Export', $export_id);
		if (!$export_entry) {
			return FALSE;
		}
		
		$found = $rf->find('Acl', 'source_id=? AND destination_id=?', array($export_entry->source_id, $destination_id));
		
		if (!$found) {
			return FALSE;
		}
		$acl = array_shift($found);
		
		$acl_data = array(
			'start_time' => strtotime($acl->start_time),
			'end_time' => strtotime($acl->end_time),
			'country_allow_list' => ($acl->country_allow_list) ? json_decode($acl->country_allow_list, TRUE) : array(),
			'country_deny_list' => ($acl->country_deny_list) ? json_decode($acl->country_deny_list, TRUE) : array(),
		);
		
		$hash = $hash = ceil($export_id / 100);
		$filename = sprintf("%012d.json", $export_id);
		$file = self::ACL_PREFIX . "/{$export_entry->farm}/{$hash}/{$filename}";
		$dir = dirname($file);
		$ret = @mkdir($dir, 0777, TRUE);
		$ret = @chmod($dir, 0777);
		$ret = file_put_contents($file, json_encode($acl_data));
		if (!$ret) {
			return FALSE;
		}
		
		return $file;
	}
	
	protected function process(Stomp_Frame $message) {
		// record start time
		$start_time = microtime(TRUE);
		echo date('Y-m-d H:i:s') . ": Start distributing image export_id: {$message->map->export_id} ...\n";

		// gather info
		$export_id = $message->map->export_id;
		$callback_url = $message->map->callback_url;

		// get distribution record
		$rf = ImageInfrastructure::getWritableRecordFactory();
		$found = $rf->find('Distribution', 'export_id=? AND destination_id=?',
			array($export_id, $this->destination_id)
		);

		if ($found) {
			$distribution_entry = array_shift($found);
			$source_file = ImageInfrastructure::getExportStorage($export_id);
			$destination_file = ImageInfrastructure::GetDistributedStorage($export_id, $this->destination_id);
			$acl_file = $this->generateAclFile($export_id);
			try {
				foreach ($this->destinations as $host) {
					$ssh = new SSHAgent($host, $this->port, $this->user, $this->public_key_file, $this->private_key_file, $this->passpharse);
					$ret = $ssh->sendFile($source_file, $destination_file);
					if ($ret === FALSE) {
						return $this->sendErrorQueue($message);
					}
					if ($acl_file) {
						$ret = $ssh->sendFile($acl_file, $acl_file);
						if ($ret === FALSE) {
							return $this->sendErrorQueue($message);
						}
					}
				}
				$distribution_entry->status = 1;
			} catch (Exception $e) {
				$distribution_entry->status = -1;
				$distribution_entry->other_info = $e->getMessage();
			}
			$ret = $rf->save_by_fields($distribution_entry, array('export_id', 'destination_id'));
			try {
				$ret = ImageInfrastructure::Callback($export_id, $this->destination_id, $distribution_entry->status, $callback_url);
			} catch (Exception $e) {
				// don't quit
				error_log("Error - Callback Failed: callback_url = $callback_url");
				error_log("Callback([{$export_id}, {$this->destination_id}, {$distribution_entry->status}, {$callback_url})");
				error_log(var_export($e, TRUE));
			}
		}

		$end_time = microtime(TRUE);
		$time_elapsed = $end_time - $start_time;
		echo date('Y-m-d H:i:s') . ": {$export_id} distributed. Time used: {$time_elapsed}s\n";
	
		return TRUE;
	}
	
}

$destination_id = 1; // HARD CODE
$rf = ImageInfrastructure::getReadableRecordFactory();
$destination_entry = $rf->findInstance('Destination', $destination_id);
$broker = $destination_entry->broker;
$queue = $destination_entry->queue;
$rf = null;

$cons = new DistributeTvbImgFarmImageConsumer('', '', null, $broker, $queue);
$cons->init($destination_id);
$cons->run();
?>
